package com.yami.shop.common.config;

import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpUtil;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.response.ResponseEnum;
import com.yami.shop.common.response.ServerResponseEntity;
import com.yami.shop.common.util.Json;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 自定义错误处理器
 * @author LGH
 */
@Slf4j
@Controller
@RestControllerAdvice
public class DefaultExceptionHandlerConfig {
    @Value("${spring.profiles.active}")
    String active;
    @Value("${server.port}")
    String port;


    private static String DING_DING_TOKEN ="https://oapi.dingtalk.com/robot/send?access_token=b786691dbbf3efe6cb6f4f2c931f7b00a103bc9df2b0c0d1ef19d12a8939c0df";
    private static final Logger logger = LoggerFactory.getLogger(DefaultExceptionHandlerConfig.class);

    @ExceptionHandler({ MethodArgumentNotValidException.class, BindException.class })
    public ResponseEntity<ServerResponseEntity<List<String>>> methodArgumentNotValidExceptionHandler(Exception e) {
        logger.error("methodArgumentNotValidExceptionHandler", e);
        List<FieldError> fieldErrors = null;
        if (e instanceof MethodArgumentNotValidException) {
            fieldErrors = ((MethodArgumentNotValidException) e).getBindingResult().getFieldErrors();
        }
        if (e instanceof BindException) {
            fieldErrors = ((BindException) e).getBindingResult().getFieldErrors();
        }
        if (fieldErrors == null) {
            return ResponseEntity.status(HttpStatus.OK)
                    .body(ServerResponseEntity.fail(ResponseEnum.METHOD_ARGUMENT_NOT_VALID));
        }

        List<String> defaultMessages = new ArrayList<>(fieldErrors.size());
        for (FieldError fieldError : fieldErrors) {
            defaultMessages.add(fieldError.getField() + ":" + fieldError.getDefaultMessage());
        }
        getMessage(e);
        return ResponseEntity.status(HttpStatus.OK)
                .body(ServerResponseEntity.fail(ResponseEnum.METHOD_ARGUMENT_NOT_VALID, defaultMessages));
    }

    @ExceptionHandler(YamiShopBindException.class)
    public ResponseEntity<ServerResponseEntity<?>> unauthorizedExceptionHandler(YamiShopBindException e){
        logger.error("mall4jExceptionHandler", e);

        ServerResponseEntity<?> serverResponseEntity = e.getServerResponseEntity();
        if (serverResponseEntity!=null) {
            return ResponseEntity.status(HttpStatus.OK).body(serverResponseEntity);
        }
        getMessage(e);
        // 失败返回消息 状态码固定为直接显示消息的状态码
        return ResponseEntity.status(HttpStatus.OK).body(ServerResponseEntity.fail(e.getCode(),e.getMessage()));
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<ServerResponseEntity<Object>> exceptionHandler(Exception e){
        logger.error("exceptionHandler", e);
        getMessage(e);
        return ResponseEntity.status(HttpStatus.OK).body(ServerResponseEntity.fail(ResponseEnum.EXCEPTION));
    }
    @Async("lazyTraceExecutor")
    void getMessage(Exception e)  {
        try {
            StackTraceElement stackTraceElement= e.getStackTrace()[0];
            String param = "## **什么？又异常啦**?" + " \r\n " +
                    "- **异常主机：** \n```\n" +  "("+getProject(port)+"-"+active + ") \n```\n" +
                    "- **异常类：** \n```\n" + stackTraceElement.getClassName() + "\n```\n" +
                    "- **异常方法：** \n```\n" + stackTraceElement.getMethodName() + "\n```\n" +
                    "- **行 号：** \n```\n" + stackTraceElement.getLineNumber() + "\n```\n" +
                    "- **异常信息：** \n```\n" + e.getMessage() + "\n```\n" +
                    "- **发生时间：** \n```\n " + DateUtil.now() + "\n```\n";
            Map<String,Object> text=new HashMap();
            Map<String,Object> json=new HashMap();
            json.put("msgtype","markdown");
            text.put("title", "项目告警通知");
            text.put("text", param);
            json.put("markdown", text);
            //发送post请求
            HttpUtil.post(DING_DING_TOKEN, Json.toJsonString(json));
        }catch (Exception es){log.info("发送钉钉异常");}
    }
    private String getProject(String port){
        String project = "";
        if ("8086".equals(port)) {
            project = "api";
        } else if ("8087".equals(port)) {
            project = "shop";
        } else if ("8088".equals(port)) {
            project = "platform";
        }
        return project;
    }

}
